package com.hfzy.ihk.web.aliyuncall.support.cloudcall.handler.asrcall;

import com.alibaba.fastjson.JSONObject;
import com.hfzy.ihk.common.util.Utils;
import com.hfzy.ihk.common.util.date.DateUtils;
import com.hfzy.ihk.common.util.string.StringTools;
import com.hfzy.ihk.facade.aliyuncall.vo.CallHistory;
import com.hfzy.ihk.web.aliyuncall.biz.AliyunAsrCallOutBiz;
import com.hfzy.ihk.web.aliyuncall.biz.AliyunCallOutBiz;
import com.hfzy.ihk.web.aliyuncall.biz.CallHistoryLastUtils;
import com.hfzy.ihk.web.aliyuncall.biz.PushDataToEsBiz;
import com.hfzy.ihk.web.aliyuncall.constant.Constants;
import com.hfzy.ihk.web.aliyuncall.constant.RedisFields;
import com.hfzy.ihk.web.aliyuncall.constant.RedisKey;
import com.hfzy.ihk.web.aliyuncall.constant.RedisTimeOut;
import com.hfzy.ihk.web.aliyuncall.support.cloudcall.base.AbstractCallOutHandler;
import com.hfzy.ihk.web.aliyuncall.support.cloudcall.event.AliyunCallOutEvent;
import com.hfzy.ihk.web.aliyuncall.support.cloudcall.handler.doublecall.AliyunCallOutHandler;
import com.hfzy.ihk.web.aliyuncall.support.websocket.WebSocketUtils;
import com.hfzy.ihk.web.aliyuncall.vo.AsrCallOutParam;
import com.hfzy.ihk.web.aliyuncall.vo.CallOutParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by YANFA on 2018/10/12.
 */
@Component
@Scope("prototype")
public class AliyunAsrCallOutHandler extends AbstractCallOutHandler<CallHistory,AliyunCallOutEvent> {

    private static final Logger logger = LoggerFactory.getLogger(AliyunAsrCallOutHandler.class);

    @Autowired
    RedisTemplate redisTemplate;


    @Autowired
    AliyunAsrCallOutBiz aliyunAsrCallOutBiz;

    @Autowired
    CallHistoryLastUtils callHistoryLastUtils;

    @Resource
    TaskExecutor pushDataToEsTaskExecutor;

    @Autowired
    PushDataToEsBiz pushDataToEsBiz;

    @Autowired
    WebSocketUtils webSocketUtils;
    /**
     * 写入缓存
     * @param data
     * @return
     */
    @Override
    protected String writeRedis(CallHistory data) {
        Map<String, String> map = new HashMap<>();
        //创建记录时间
        String createTimeStr = DateUtils.formatDate(data.getCreateTime(), DateUtils.DATE_FORMAT_DATETIME_SSS);

        if(!data.getCommitOk()){ //已经推送ES入库所以没必要再写入redis
            logger.debug("{} commit failed， don't writed redis,sessionId：{}",data.getSessionId());
            return Constants.FAIL;
        }

        logger.info("writed redis,sessionId：{}", data.getSessionId());
        //提交前就有的数据
        map.put(RedisFields.CREATE_USER_ID, data.getCreateUserId().toString());
        map.put(RedisFields.CREATE_TIME, createTimeStr);
        map.put(RedisFields.CALL_HISTORY_TODAY,data.getToday());
        map.put(RedisFields.CALL_HISTORY_MAIN_CALL_PHONE, data.getMainCallPhone());
        //map.put(RedisFields.CALL_HISTORY_TARGET_CALL_PHONE, data.getTargetCallPhone());
        map.put(RedisFields.CALL_HISTORY_SHOW_NUM, data.getShowNum());
        map.put(RedisFields.CALL_HISTORY_IMS, data.getIms());
        map.put(RedisFields.CALL_HISTORY_SESSION_ID, data.getSessionId());
        map.put(RedisFields.CALL_HISTORY_DATA_ID, data.getDataId().toString());

        map.put(RedisFields.CALL_HISTORY_MACHINE_FROM, data.getMachineFrom());
        map.put(RedisFields.CALL_HISTORY_WHERE_FROM, data.getWhereFrom().toString());
        map.put(RedisFields.CALL_HISTORY_PAGE_FROM, data.getPageFrom().toString());
        map.put(RedisFields.CALL_HISTORY_MAIN_CALL_TYPE, data.getMainCallType().toString());
        map.put(RedisFields.CALL_HISTORY_CALL_TYPE, data.getCallType().toString());
        map.put(RedisFields.CALL_HISTORY_CITY, data.getCity().toString());

        map.put(RedisFields.CALL_HISTORY_CUSTOMER_NAME, data.getCustomerName());
        map.put(RedisFields.CALL_HISTORY_COMMIT_TO, data.getCommitTo().toString());
        map.put(RedisFields.CALL_HISTORY_PROJECT, data.getProject() == null ? "NULL" : data.getProject());
        map.put(RedisFields.CALL_HISTORY_PROPERTY_NO, data.getPropertyNo() == null ? "NULL" : data.getPropertyNo());
        map.put(RedisFields.CALL_HISTORY_OBJECT_ID, data.getObjectId() == null ? "NULL" : data.getObjectId());
        map.put(RedisFields.CALL_HISTORY_COMMIT_TIME, DateUtils.formatDate(data.getCommitTime(), DateUtils.DATE_FORMAT_DATETIME_SSS));
        map.put(RedisFields.CALL_TASK_ID, data.getCallTaskId() == null ? "NULL" : data.getCallTaskId());
        //提交后生成的数据
        if(!StringTools.isEmpty(data.getCallOutResultMessage()))
            map.put(RedisFields.CALL_OUT_RESULT_MESSAGE,data.getCallOutResultMessage());

        if(!StringTools.isEmpty(data.getCallOutResultCode()))
            map.put(RedisFields.CALL_OUTR_ESULT_CODE,data.getCallOutResultCode());


        map.put(RedisFields.CALL_HISTORY_COMMIT_OK,data.getCommitOk().toString());

        //对方的业务id
        map.put(RedisFields.CALL_HISTORY_MESSAGE_ID, data.getMessageId());


        if(logger.isDebugEnabled()) {
            for (String b : map.keySet()) {
                logger.debug("before write redis hash--> key:" + b + " value:" + map.get(b));
            }
        }
        /*保存呼叫数据,3天 推送成功以后会自动清除*/
        redisTemplate.opsForHash().putAll(RedisKey.CALL_HISTORY_RPIX + data.getSessionId(),map);
        redisTemplate.expire(RedisKey.CALL_HISTORY_RPIX + data.getSessionId(), RedisTimeOut.CACHE_THREE_DAY, TimeUnit.SECONDS);

        //将taskId和sessionId的关系保持到redis 一天过期
        if("11".equals(String.valueOf(data.getWhereFrom()))) {//如果是给保利测试的那么不用保利这个关系，之后通过这个可以判断该识别结果是不是保利那边的
            redisTemplate.opsForValue().set(data.getSessionId(), "-1");
        }else{
            redisTemplate.opsForValue().set(data.getSessionId(), data.getPackageId() + ":" + data.getCallTaskId(), RedisTimeOut.CACHE_ONE_DAY, TimeUnit.SECONDS);
        }
        map = null;
        return Constants.SUCCESS;
    }


    /**
     * 写redis失败处理
     * @param data
     * @return
     */
    @Override
    protected String handleWriteRedisFailed(CallHistory data) {
        logger.info("---->aliyun 写入 redis  失败 sessionId:{}",data.getSessionId());
        return null;
    }

    /**
     * 提交操作
     * @param data
     * @return
     */
    @Override
    protected String commit(CallHistory data) {

        logger.info("----->开始提交asr 外呼信息：{}",data.toString());

        String result = null;
        try {
            data.setCommitTime(DateUtils.getDateFromString(DateUtils.formatDate(new Date(),DateUtils.DATE_FORMAT_DATETIME_SSS),DateUtils.DATE_FORMAT_DATETIME_SSS));  //呼出提交到阿里的时间

            AsrCallOutParam asrCallOutParam = new AsrCallOutParam();

            asrCallOutParam.setShowNum(data.getShowNum());
            asrCallOutParam.setMainCallPhone(data.getMainCallPhone());
            asrCallOutParam.setActionCodeBreak(data.getActionCodeBreak());
            asrCallOutParam.setVoiceCode(data.getVoiceCode());
            asrCallOutParam.setExtend(data.getSessionId());
            asrCallOutParam.setVoiceCodeParam(data.getVoiceText());
            Map<String,String> map = aliyunAsrCallOutBiz.AsrCallOutOpt(asrCallOutParam);
            if(map.get("callId")!=null){
                data.setMessageId(map.get("callId"));
            }
            if(map.get("callOutCode")!=null){
                data.setCallOutResultCode(map.get("callOutCode"));
            }
            if(map.get("msg")!=null){
                data.setCallOutResultMessage(map.get("msg"));
            }
            if(map.get("requestId")!=null){
                data.setCallOutrequestId(map.get("requestId"));
            }

            if(map.get("result").equals(Constants.SUCCESS)){
                data.setCommitOk(true);
                result = Constants.SUCCESS;
            }else{
                data.setCommitOk(false);
                result = Constants.FAIL;
            }
            try {
                data.setToday(Utils.date2DateString(data.getCreateTime()));
            }catch (Exception e){
                logger.error("--->set today fail",e);
            }
        }catch (Exception e){
            //异常这里因为不是调用api导致异常的所以返回成功
            result = Constants.SUCCESS;
        }
        return result;
    }

    /**
     * 提交失败处理
     * @param data
     * @return
     */
    @Override
    protected String commitFail(CallHistory data) {
        try {
            Map<String,String> map = redisTemplate.opsForHash().entries(data.getSessionId());
            String jsonStr = JSONObject.toJSONString(map);
            pushDataToEsTaskExecutor.execute(() -> {
                pushDataToEsBiz.pushCallHistoryToEs(data.getSessionId(), jsonStr, RedisKey.CALL_HISTORY_RPIX + data.getSessionId());
            });
            return Constants.SUCCESS;
        }catch (Exception e){
            try {
                redisTemplate.opsForSet().add(RedisKey.PUSH_TO_ES_FAILED_HISTORY,data.getSessionId());
            }catch (Exception e1){
                logger.error("将推送ES 失败数据放入redis 失败！sessionId：{}",data.getSessionId(),e1);
            }
            logger.error("====>推送Es 的线程池爆了",e);
            return Constants.FAIL;
        }

    }


    /**
     * 提交成功以后处理
     * @param data
     */
    @Override
    protected void handleAfterCommit(CallHistory data) {

        //提交成功推送给客户端
        Map<String,String> map = new HashMap<>();
        String nowStr = DateUtils.formatDate(new Date(), DateUtils.DATE_FORMAT_DATETIME_SSS);
        if(data.getCommitOk()){
            map.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_COMMIT_SUCCESS);
            map.put(Constants.WEB_SOCKET_JSON_KEY_SHOW_NUM,  data.getShowNum());
            //缓存最后使用某主显号码拨打给某客户号码的信息
            try {
                callHistoryLastUtils.addCallHistoryLastByShowNum(data.getShowNum(), data.getMainCallPhone(), data.getTargetCallPhone(),
                        data.getCreateUserId().toString(), data.getDataId().toString(), data.getMainCallType().toString(), data.getCustomerName(), data.getPageFrom().toString(), data.getProject(), nowStr,String.valueOf(data.getCity()));

            }catch (Exception e){
                logger.error("缓存最后使用的主显号码失败,:sessionId:{}",data.getSessionId(),e);
            }
        }else {
            map.put(Constants.WEB_SOCKET_JSON_KEY_MSG_TYPE, Constants.WEB_SOCKET_MSG_TYPE_COMMIT_FAILED);
            map.put(Constants.WEB_SOCKET_JSON_KEY_DESC, data.getCallOutResultMessage());
        }
        map.put(Constants.WEB_SOCKET_JSON_KEY_TIME, nowStr);
        map.put(Constants.WEB_SOCKET_JSON_KEY_SESSION_ID, data.getSessionId());
        map.put(Constants.WEB_SOCKET_JSON_KEY_DATA_ID, String.valueOf(data.getDataId()));
        map.put(Constants.WEB_SOCKET_JSON_KEY_PAGE_FROM, String.valueOf(data.getPageFrom()));
        map.put(Constants.WEB_SOCKET_JSON_KEY_MACHINE_FROM, data.getMachineFrom());
        //将状态推到客户端
        webSocketUtils.pushToClientByToken(data.getMachineFrom(), JSONObject.toJSONString(map));

    }

    /**
     * 生成id失败处理
     * @param data
     */
    @Override
    protected void handleIdgeneratedFailed(CallHistory data) {
        logger.info("-->aliyun 申请sessionId 失败");

    }


}
